﻿using Microsoft.AspNetCore.Mvc.ModelBinding;
using ModelBinder.Host.Infrastructures.Features;
using Newtonsoft.Json;

namespace ModelBinder.Host.Infrastructures.ModelBinders;

public class CustomJsonValueModelBinder : IModelBinder
{
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var httpContext = bindingContext.HttpContext;
        var httpBodyFeature = httpContext.Features.Get<IHttpBodyFeature>();
        var body = httpBodyFeature.Body;

        //对于Body传空的场景，走默认BodyModelBinder即可
        if (string.IsNullOrEmpty(body) || body == "null")
        {
            return;
        }

        Dictionary<string, object> jsonObject = null;

        //https://github.com/egorpavlikhin/JsonParametersModelBinder/blob/master/JsonBinder/JsonBinder.cs
        try
        {
            jsonObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(body);
        }
        catch (Exception)
        {
            return;
        }

        //如果方法参数名和模型内属性名重名了，则序列化对象就会有问题了
        if (jsonObject.TryGetValue(bindingContext.FieldName, out var value))
        {
            var jsonBody = JsonConvert.SerializeObject(value);
            var type = bindingContext.ModelMetadata.ModelType;
            var model = JsonConvert.DeserializeObject(jsonBody, type);
            bindingContext.ModelState.Clear();
            bindingContext.Result = ModelBindingResult.Success(model);
            return;
        }
    }
}